package com.lc.ibps.platform.rest.data;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.lc.ibps.api.base.page.Page;
import com.lc.ibps.api.base.query.FieldLogic;
import com.lc.ibps.api.base.query.FieldRelation;
import com.lc.ibps.api.base.query.QueryFilter;
import com.lc.ibps.api.base.query.QueryOP;
import com.lc.ibps.api.bo.model.IDataObject;
import com.lc.ibps.api.bo.service.IBoInstanceService;
import com.lc.ibps.api.form.constants.RightsScope;
import com.lc.ibps.api.form.service.IFormRightsService;
import com.lc.ibps.api.form.sql.model.TreeDisplayField;
import com.lc.ibps.api.form.vo.FormPermissionVo;
import com.lc.ibps.base.bo.constants.DataSaveMode;
import com.lc.ibps.base.bo.exception.DataObjectException;
import com.lc.ibps.base.bo.persistence.entity.BoDefPo;
import com.lc.ibps.base.bo.repository.BoDefRepository;
import com.lc.ibps.base.core.engine.script.GroovyScriptEngine;
import com.lc.ibps.base.core.util.AppUtil;
import com.lc.ibps.base.core.util.BeanUtils;
import com.lc.ibps.base.core.util.json.JsonUtil;
import com.lc.ibps.base.core.util.string.StringConverter;
import com.lc.ibps.base.core.util.string.StringUtil;
import com.lc.ibps.base.db.model.DefaultFieldLogic;
import com.lc.ibps.base.db.model.DefaultQueryFilter;
import com.lc.ibps.base.db.mybatis.domain.DefaultPage;
import com.lc.ibps.base.web.context.ContextUtil;
import com.lc.ibps.base.web.json.PageJson;
import com.lc.ibps.base.web.util.RequestUtil;
import com.lc.ibps.cloud.entity.APIRequest;
import com.lc.ibps.cloud.entity.APIRequestPage;
import com.lc.ibps.cloud.entity.APIResult;
import com.lc.ibps.form.data.constants.DataTemplateShowType;
import com.lc.ibps.form.data.helper.DataTemplateBuilder;
import com.lc.ibps.form.data.persistence.entity.DataTemplatePo;
import com.lc.ibps.form.data.persistence.vo.ResponseDataTemplateVo;
import com.lc.ibps.form.data.service.DataTemplateService;
import com.lc.ibps.form.form.helper.FormDefDataBuilder;
import com.lc.ibps.form.form.persistence.entity.FormBoPo;
import com.lc.ibps.form.form.persistence.entity.FormDefPo;
import com.lc.ibps.form.form.repository.FormDefRepository;
import com.lc.ibps.web.controller.BaseApiController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * 数据模板 接口
 *
 * <pre>
 *  
 * 构建组：ibps-platform-webapi
 * 作者：zhongjh
 * 邮箱：zjh20140614@163.com
 * 日期：2018年5月31日-下午3:51:23
 * 版权：广州流辰信息技术有限公司版权所有
 * </pre>
 */
@RequestMapping(value="/api/webapi/dataTemplateService")
@Api(value = "/dataTemplateService", tags = "表单管理-数据模板服务")
@RestController
public class DataTemplateController  extends BaseApiController  {

	private DataTemplateService dataTemplateService;
	private FormDefRepository formDefRepository;
	private IFormRightsService formRightsService;
	private BoDefRepository boDefRepository;
	private  IBoInstanceService boInstanceService;

	public DataTemplateController() {
		dataTemplateService = AppUtil.getBean(DataTemplateService.class);
		formDefRepository = AppUtil.getBean(FormDefRepository.class);
		formRightsService = AppUtil.getBean(IFormRightsService.class);
		boDefRepository = AppUtil.getBean(BoDefRepository.class);
		boInstanceService = AppUtil.getBean(IBoInstanceService.class);
	}

	@ApiOperation(value = "通过key查询数据模版", notes = "通过key查询数据模版")
	@RequestMapping(value="/getByKey",method=RequestMethod.GET)
	public APIResult<String> getByKey(
			@ApiParam(name="key", value = "key", required = true) 
			@RequestParam(name = "key", required = true) String key)
			throws Exception {
		APIResult<String> result = new APIResult<>();
		try {
			if (StringUtil.isNotEmpty(key)) {
				DataTemplatePo po = dataTemplateService.getByKey(key);
				JSONObject data = DataTemplateBuilder.buildData(po, true, true);
				result.setData(data.toString());
			} else {
				result = getResult(result, FAIL, "未获取数据模版key");
			}

		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "获取数据模版出错了", e);
		}
		return result;
	}
	
	@ApiOperation(value = "通过id查询数据模版", notes = "通过id查询数据模版")
	@RequestMapping(value="/getById",method=RequestMethod.GET)
	public APIResult<String> getById(
			@ApiParam(name="id", value = "id", required = true) 
			@RequestParam(name = "id", required = true) String id)
			throws Exception {
		APIResult<String> result = new APIResult<>();
		try {
			if (StringUtil.isNotEmpty(id)) {
				DataTemplatePo po = dataTemplateService.getById(id);
				JSONObject data = DataTemplateBuilder.buildData(po, true, true);
				result.setData(data.toString());
			} else {
				result = getResult(result, FAIL, "未获取数据模版key");
			}

		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "查询数据模版出错了", e);
		}
		return result;
	}
	
	
	@ApiOperation(value = "查询数据信息", notes = "查询数据信息")
	@RequestMapping(value="/queryDataJson",method=RequestMethod.POST)
	public APIResult<Object> queryDataJson(
			@ApiParam(name = "request", value = "传入查询请求json字符串", required = true) 
			@RequestBody(required = true) APIRequest request)
			throws Exception {
		
		APIResult<Object> result = new APIResult<Object>();
		String key = request.getParameter("key");
		String dynamicParams = request.getParameter("dynamicParams");
		String filterConditionKey = request.getParameter("filterConditionKey");
		
		try {
			DefaultQueryFilter queryFilter = (DefaultQueryFilter) getQuerFilter(request);
			DataTemplatePo po = dataTemplateService.getByKey(key);
			
			JSONObject responseData = DataTemplateBuilder.buildDataTemplateJson(po,true);
			if (JsonUtil.isEmpty(responseData)) {
				result = getResult(result, FAIL, "请输入参数！");
				return result;
			}
			
			String showType = JsonUtil.getString(responseData, "showType");
			responseData.element("dynamic_params", dynamicParams);
			Object data = null;
			if(DataTemplateShowType.LIST.key().equals(showType) ){
				APIRequestPage page = request.getRequestPage();
				if(BeanUtils.isNotEmpty(page)){
					Page pageable = getQueryDataPage(responseData, page.getPageNo(), page.getLimit());
					queryFilter.setPage(pageable);
				}
		
				List<?> list = dataTemplateService
						.queryForList(new ResponseDataTemplateVo(responseData, queryFilter, filterConditionKey));
			
				data =  getAPIPageList(list);
			}else{
				TreeDisplayField displayField = getTreeDisplayField(responseData);
				Map<String, Object> map = new HashMap<String, Object>();
				
				queryFilter.setPage(null);
				setRootPid(displayField, queryFilter, map);

				List<?> list  = dataTemplateService.geTreeData(new ResponseDataTemplateVo(responseData, queryFilter));
			
				for (String k : map.keySet()) { 
					result.addVariable( k, map.get(k));
				} 
				data =  getAPIPageList(list);
			}

			result.setData(data);
			return result;
		} catch (Exception e) {
			return getExceptionResult(result, ERROR, "查询数据模版信息出错了", e);
		}
		
	}
	

	@ApiOperation(value = "查询列表数据", notes = "查询列表数据")
	@RequestMapping(value="/queryDataTableJson",method=RequestMethod.POST)
	public APIResult<PageJson> queryDataTableJson(
			@ApiParam(name="key", value = "数据模版key", required = true) 
			@RequestParam(name = "key", required = true) String key,
			@ApiParam(name="dynamicParams", value = "动态参数", required = false) 
			@RequestParam(name = "dynamicParams", required = false) String dynamicParams,
			@ApiParam(name="filterConditionKey", value = "过滤条件key", required = false) 
			@RequestParam(name = "filterConditionKey", required = false) String filterConditionKey,
			@ApiParam(name="page", value = "页码", required = false, defaultValue = "1") 
			@RequestParam(name = "page", required = false) String page,
			@ApiParam(name="limit", value = "页容量", required = false, defaultValue = "15") 
			@RequestParam(name = "limit", required = false) String limit)
			throws Exception {
		APIResult<PageJson> result = new APIResult<>();
		try {
			DataTemplatePo po = dataTemplateService.getByKey(key);
			JSONObject responseData = DataTemplateBuilder.buildDataTemplateJson(po,true);
			
	
			if (JsonUtil.isEmpty(responseData)) {
				return getResult(result, FAIL, "请输入参数！");
			}
			responseData.element("dynamic_params", dynamicParams);
			
			Page pageable = getQueryDataPage(responseData, Integer.parseInt(page), Integer.parseInt(limit));
			DefaultQueryFilter queryFilter = new DefaultQueryFilter();
			queryFilter.setPage(pageable);
			FieldLogic fieldLogic = new DefaultFieldLogic(FieldRelation.AND);
			queryFilter.setFieldLogic(fieldLogic);

			List<?> list = dataTemplateService
					.queryForList(new ResponseDataTemplateVo(responseData, queryFilter, filterConditionKey));

			// JSONArray fields = responseData.getJSONArray("fields");

			result.setData(new PageJson(list));
			return result;
		} catch (Exception e) {
			return getExceptionResult(result, ERROR, "查询列表数据模版出错了", e);
		}

	}

	@ApiOperation(value = "查询树形数据", notes = "查询树形数据")
	@RequestMapping(value="/queryTreeDataJson",method=RequestMethod.POST)
	public APIResult<Map<String, Object>> queryTreeDataJson(
			@ApiParam(name="key", value = "数据模版key", required = true) 
			@RequestParam(name = "key", required = true) String key,
			@ApiParam(name="dynamicParams", value = "动态参数", required = false) 
			@RequestParam(name = "dynamicParams", required = false) String dynamicParams,
			@ApiParam(name="filterConditionKey", value = "过滤条件key", required = false) 
			@RequestParam(name = "filterConditionKey", required = false) String filterConditionKey)
			throws Exception {
		APIResult<Map<String, Object>> result = new APIResult<>();
		try {
			DataTemplatePo po = dataTemplateService.getByKey(key);
			JSONObject responseData = DataTemplateBuilder.buildDataTemplateJson(po,true);
			
	
			if (JsonUtil.isEmpty(responseData)) {
				return getResult(result, FAIL, "请输入参数！");
			}
			responseData.element("dynamic_params", dynamicParams);
			if (JsonUtil.isEmpty(responseData)) {
				return getResult(result, FAIL, "请输入参数！");
			}
			// QueryFilter queryFilter = this.getQuerFilter(request, null);

			DefaultQueryFilter queryFilter = new DefaultQueryFilter();
			FieldLogic fieldLogic = new DefaultFieldLogic(FieldRelation.AND);
			queryFilter.setFieldLogic(fieldLogic);
			TreeDisplayField displayField = getTreeDisplayField(responseData);

			Map<String, Object> map = new HashMap<String, Object>();

			setRootPid(displayField, queryFilter, map);

			List<?> list = dataTemplateService.geTreeData(new ResponseDataTemplateVo(responseData, queryFilter));

			map.put("result", true);
			map.put("data", list);
			result.setData(map);
			return result;

		} catch (Exception e) {
			return getExceptionResult(result, ERROR, "查询列表数据模版出错了", e);
		}
	}

	private Map<String, Object> setRootPid(TreeDisplayField displayField, QueryFilter queryFilter,
			Map<String, Object> map) {
		String rootPId = "";
		String rootLabel = "";
		if (BeanUtils.isEmpty(displayField)) {
			map.put("rootPId", rootPId);
			map.put("rootLabel", rootLabel);
			return map;
		}
		rootPId = displayField.getRootPid();
		rootLabel = displayField.getRootLabel();
		// || BeanUtils.isEmpty(displayField.getRootPid())
		if (BeanUtils.isEmpty(rootPId)) {
			map.put("rootPId", rootPId);
			map.put("rootLabel", rootLabel);
			return map;
		}

		boolean isScript = displayField.isScript();
		if (isScript) {// 是脚本，开始解释这段脚本
			GroovyScriptEngine groovyScriptEngine = (GroovyScriptEngine) AppUtil.getBean(GroovyScriptEngine.class);
			rootPId = groovyScriptEngine.executeObject(rootPId, null).toString();
		}
		map.put("rootPId", rootPId);
		map.put("rootLabel", rootLabel);
		return map;
	}

	private TreeDisplayField getTreeDisplayField(JSONObject data) {
		Object o = data.get("display_columns");
		if (JsonUtil.isEmpty(o))
			return null;
		if (o instanceof JSONArray)
			return null;
		JSONObject column = (JSONObject) o;

		TreeDisplayField result = new TreeDisplayField();
		result.setIdKey(JsonUtil.getString(column, "id_key"));
		result.setPidKey(JsonUtil.getString(column, "pid_key"));
		result.setNameKey(JsonUtil.getString(column, "name_key"));
		result.setScript(JsonUtil.getBool(column, "is_script"));
		result.setRootPid(JsonUtil.getString(column, "root_pid"));
		result.setRootLabel(JsonUtil.getString(column, "root_label"));
		return result;
	}

	/**
	 * 
	 * 获取是否分页
	 *
	 * @param request
	 * @param responseData
	 * @return
	 */
	private Page getQueryDataPage(JSONObject responseData, int page, int pageSize) {
		boolean isNeedPage = JsonUtil.getBool(responseData, "need_page", true);
		if (isNeedPage) {
			int pageInt = BeanUtils.isNotEmpty(page)?page:1;
			int pageSizeInt = BeanUtils.isNotEmpty(pageSize)?pageSize:15;
			return new DefaultPage(pageInt,pageSizeInt);
		}
		return null;
	}
	
	
	/**
	 * 通过id获取关联的数据
	 *
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = "通过id获取关联的数据", notes = "查通过id获取关联的数据")
	@RequestMapping(value="/getDataById",method=RequestMethod.GET)
	public APIResult<Object> getDataById(
			@ApiParam(name="key", value = "数据模版key", required = true) 
			@RequestParam(name = "key", required = true) String key,
			@ApiParam(name="id", value = "id值", required = true) 
			@RequestParam(name = "id", required = true) String idValue) throws Exception {

		APIResult<Object> result = new APIResult<>();
		try {
			if (StringUtil.isNotEmpty(key)) {
				DataTemplatePo po = dataTemplateService.getByKey(key);
				if (BeanUtils.isEmpty(po)) {
					result = getResult(result, WARN, "获取数据模版为空");
				} else {
					JSONObject responseData = DataTemplateBuilder.buildDataTemplateJson(po, false);
					DefaultQueryFilter queryFilter = new DefaultQueryFilter();
					queryFilter.setPage(null);
					queryFilter.addFilter(JsonUtil.getString(responseData, "unique"), idValue, QueryOP.EQUAL);
					List<?> list = dataTemplateService
							.queryForList(new ResponseDataTemplateVo(responseData, queryFilter));
					result.setData(BeanUtils.isEmpty(list) ? "" : list.get(0));
				}
			} else {
				result = getResult(result, WARN, "未获取数据模版key");
			}
		} catch (Exception e) {
			result =  getExceptionResult(result, ERROR, "通过id获取关联的数据出错", e);
		}

		return result;
	}
	
	
	@ApiOperation(value = "获取表单数据", notes = "获取表单数据")
	@RequestMapping(value="/getFormData",method=RequestMethod.GET)
	public APIResult<Map<String, Object>> getFormData(
			@ApiParam(name="formKey", value = "formKey", required = true) 
			@RequestParam(name = "formKey", required = true) String formKey,
			@ApiParam(name="templateKey", value = "templateKey", required = true) 
			@RequestParam(name = "templateKey", required = true) String templateKey,
			@ApiParam(name="hasButton", value = "hasButton", required = true) 
			@RequestParam(name = "hasButton", required = true) Boolean hasButton,
			@ApiParam(name="pk", value = "pk", required = false) 
			@RequestParam(name = "pk", required = false) String pk)
			throws Exception {
		APIResult<Map<String, Object>> result = new APIResult<Map<String, Object>>();
		try {
			FormDefPo po = formDefRepository.getMainByFormKey(formKey);
			String formData =formDefRepository.getFormData( po.getId());

			//===============表单权限=========================
			String rightsScope =  RightsScope.DATA.key(); 
			Map<String, String> rightsMap = new HashMap<String, String>();
			rightsMap.put(FormPermissionVo.RIGHTS_KEY, BeanUtils.isNotEmpty(templateKey) ? templateKey : null);
			// 表单权限
			String permissions = formRightsService.getPermission(new FormPermissionVo(RightsScope.fromKey(rightsScope),
					ContextUtil.getCurrentUserId(), formKey, rightsMap));
			//===============表单数据=========================
			IDataObject dataObject = null;
			//编辑的数据
			if (StringUtil.isNotEmpty(pk)) {
				JSONObject jsonObject = JSONObject.fromObject(formData);
				String code = jsonObject.getString("code");
				FormBoPo formBo = formDefRepository.getFormBoByFormKey(formKey);
				BoDefPo boDefPo = boDefRepository.get(formBo.getBoId());
				dataObject = boInstanceService.getDataObject(DataSaveMode.TABLE, pk, code, boDefPo.getVersion());
			}
			String   buttons =  "";//TODO 
			if(!hasButton){
				//刷新页面 需要加载数据模版按钮的数据
			}
			
			result.setData(b()
					.a("formDef", formData)
					.a("permissions", permissions)
					.a("buttons", buttons)
					.a("formData",  BeanUtils.isNotEmpty(dataObject) ? dataObject.getData() : null)
					.p());
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "获取表单数据", e);
		}
		return result;
	}

	
	/**
	 * 保存表单数据
	 *
	 * @param request
	 * @param response
	 * @return 
	 * @throws Exception
	 */
	@ApiOperation(value = "保存表单数据", notes = "保存表单数据")
	@RequestMapping(value="/saveFormData",method=RequestMethod.POST)
	public APIResult<String> saveFormData(
			@RequestParam(name = "data", required = true) @ApiParam(name = "data", value = "表单数据", required = true) String data,
			@RequestParam(name = "pk", required = false) @ApiParam(name = "pk", value = "主键", required = false) String pk,
			@RequestParam(name = "code", required = true) @ApiParam(name = "code", value = "业务对象cod", required = true) String code,
			@RequestParam(name = "formKey", required = false) @ApiParam(name = "formKey", value = "表单Key", required = false) String formKey,
			@RequestParam(name = "version", required = false,defaultValue="0") @ApiParam(name = "version", value = "版本", required = false) String version
			) throws Exception {
		APIResult<String> result = new APIResult<String>();
		String saveType = DataSaveMode.TABLE;
		IDataObject dataObject = null;
		Integer boVersion = 0;
		try {
			FormDefPo formDefPo = formDefRepository.getByFormKey(formKey);
			FormBoPo formBo = formDefPo.getFormBo();
			BoDefPo boDefPo = boDefRepository.get(formBo.getBoId());
			boVersion = boDefPo.getVersion();
			if (StringUtil.isNotEmpty(pk)) {
				dataObject = boInstanceService.getDataObject(saveType, pk, code, boVersion);
			}
			// 将前台的BO数据与原有BO数据 融合（前台的BO数据可能只有一部分数据）
			if (BeanUtils.isEmpty(dataObject)) {
				dataObject = boInstanceService.createDataObject(code, boVersion, data);
			} else {
				boInstanceService.mergerDataObject(dataObject, data);
			}

			dataObject.setCurUserId(ContextUtil.getCurrentUserId());
			dataObject.setTenantId(ContextUtil.getCurrentTenantId());
			dataObject.setOptIp(RequestUtil.getIpAddr(request));
			dataObject.setPageVersion(StringConverter.toInteger(version));
			// 设置表单字段的数据
			dataObject.setFormOptions(FormDefDataBuilder.buildFormOptionData(formDefPo, data));

			// 保存数据
			boInstanceService.save(saveType, dataObject);

		} catch (DataObjectException e) {
			result = getExceptionResult(result, ERROR, "保存表单数据验证失败", e);
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "保存表单数据失败", e);
		}
		return result;
	}
	
	/**
	 * 批量删除【业务数据模版的表单数据】记录
	 *
	 * @param request
	 * @param response
	 * @return 
	 * @throws Exception
	 */
	@ApiOperation(value = "删除业务数据模版的表单数据", notes = "删除业务数据模版的表单数据")
	@RequestMapping(value="/removeFormData",method=RequestMethod.POST)
	public APIResult<String> removeFormData(	
			@RequestParam(name = "id", required = false) @ApiParam(name = "id", value = "主键", required = true) String id ,
			@RequestParam(name = "formKey", required = false) @ApiParam(name = "formKey", value = "表单Key", required = false) String formKey) throws Exception {
		APIResult<String> result = new APIResult<String>();
		try {
			// 获得待删除的id
			String[] ids  = id.split(",");
			FormBoPo formBo = formDefRepository.getFormBoByFormKey(formKey);
			BoDefPo boDefPo = boDefRepository.get(formBo.getBoId());
			// 构造领域对象和保存数据
			boInstanceService.removeDataObject(DataSaveMode.ALL, formBo.getBoCode(), boDefPo.getVersion(), ids);
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "删除表单数据失败", e);
		}
		return result;
	}
	

}
